home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-09-23 | 55.7 KB | 2,034 lines |
- Newsgroups: comp.sources.misc
- organization: not yet
- keywords: ZIP archive pkzip
- summary: unarchive for ZIP archives under Unix
- subject: v08i043: UnZip for Unix
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: george@gatech.edu@rebel.UUCP (George M. Sipe)
-
- Posting-number: Volume 8, Issue 43
- Submitted-by: george@gatech.edu@rebel.UUCP (George M. Sipe)
- Archive-name: unzip_gs
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # README
- # crc32.c
- # crc32.h
- # unzip.c
- # unzip.doc
- # This archive created: Sun Sep 17 15:30:42 1989
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'README'
- then
- echo shar: "will not over-write existing file 'README'"
- else
- sed 's/^X//' << \SHAR_EOF > 'README'
- XEnclosed is version 2.0 of UnZip by Samuel H. Smith. This software
- Xcan unarchive any .ZIP file including those created by the recently
- Xreleased pkzip version 1.01. Personally, I prefer zoo for many
- Xreasons, but there will be zip archives out there and this can help.
- X
- XUnfortunately, the software as released is dependent on the TurboC
- Xruntime library, the 80x86 byte ordering, and compiler optimization
- Xassumptions. Not very good at all for easy porting to Unix, or for that
- Xmatter, any other C compiler/machine combination. I have made some
- Xsignificant improvements to create UnZip 2.0.1 in order to increase
- Xportability, to run under Unix, and to compile on PC's under MicroSoft
- XC. This software has NOT been extensively tested, but appears to
- Xwork well so far.
- X
- XThis version will be sent to the author just as soon as I can finally
- Xget throught to his BBS. I had sent him the same improvements for his
- Xlast version (1.5) and explained the benefits of not having zillions of
- Xmachine specific versions, but to no avail (there are Amiga and other
- Xhacks out there - mine should be generally more portable). Sam's
- Xlicence permits this modified distribtion when the source is included,
- Xas it is here.
- X
- XMy changes among other things, perform such tasks as AUTOMATICALLY
- Xadjusting operation for any byte-ordering (if HIGH_LOW is defined)
- Xand handling C compilers which do not pack structures on 2 byte
- Xboundaries (i.e. move 'longint's to the next 4 byte boundary - this
- Xis a common, and frequently unstoppable, optimization).
- X
- X
- XGeorge M. Sipe, Phone: (404) 447-4731
- X537 Lakeshore Drive, Berkeley Lake, GA 30136-3035
- XUUCP: ...!{decvax,linus,rutgers}!gatech!rebel!george
- SHAR_EOF
- fi
- if test -f 'crc32.c'
- then
- echo shar: "will not over-write existing file 'crc32.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'crc32.c'
- X/* -------------------------------------------------------------------- */
- X/* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
- X/* code or tables extracted from it, as desired without restriction. */
- X/* */
- X/* First, the polynomial itself and its table of feedback terms. The */
- X/* polynomial is */
- X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
- X/* */
- X/* Note that we take it "backwards" and put the highest-order term in */
- X/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
- X/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
- X/* the MSB being 1. */
- X/* */
- X/* Note that the usual hardware shift register implementation, which */
- X/* is what we're using (we're merely optimizing it by doing eight-bit */
- X/* chunks at a time) shifts bits into the lowest-order term. In our */
- X/* implementation, that means shifting towards the right. Why do we */
- X/* do it this way? Because the calculated CRC must be transmitted in */
- X/* order from highest-order term to lowest-order term. UARTs transmit */
- X/* characters in order from LSB to MSB. By storing the CRC this way, */
- X/* we hand it to the UART in the order low-byte to high-byte; the UART */
- X/* sends each low-bit to hight-bit; and the result is transmission bit */
- X/* by bit from highest- to lowest-order term without requiring any bit */
- X/* shuffling on our part. Reception works similarly. */
- X/* */
- X/* The feedback terms table consists of 256, 32-bit entries. Notes: */
- X/* */
- X/* The table can be generated at runtime if desired; code to do so */
- X/* is shown later. It might not be obvious, but the feedback */
- X/* terms simply represent the results of eight shift/xor opera- */
- X/* tions for all combinations of data and CRC register values. */
- X/* */
- X/* The values must be right-shifted by eight bits by the "updcrc" */
- X/* logic; the shift must be unsigned (bring in zeroes). On some */
- X/* hardware you could probably optimize the shift in assembler by */
- X/* using byte-swap instructions. */
- X/* polynomial $edb88320 */
- X/* */
- X/* -------------------------------------------------------------------- */
- X
- Xlong crc_32_tab[] = {
- X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- X 0x2d02ef8dL
- X };
- X
- X#ifndef TURBOC
- Xtypedef unsigned char byte;
- X#endif /* !TURBOC */
- X
- X#define UPDCRC32(res,oct) \
- X res=crc_32_tab[(byte)res ^ (byte)oct] ^ ((res >> 8) & 0x00FFFFFFL)
- X
- X/*
- X * Inline assembly version of 32 bit CRC calculation
- X * Copyright 1989 Samuel H. Smith
- X *
- X * You may use this program, or code extracted from it,
- X * as desired without restriction.
- X *
- X */
- X
- Xextern long crc32val;
- X
- X/* update running CRC calculation with contents of a buffer */
- X
- X#ifndef OLDC
- Xvoid UpdateCRC(unsigned char *s, register int len)
- X#else
- Xvoid UpdateCRC(s, len)
- Xunsigned char *s;
- Xregister int len;
- X#endif /* OLDC */
- X{
- X#ifndef TURBOC
- X while (len--) {
- X UPDCRC32(crc32val, *s++);
- X }
- X#else
- X asm push cx
- X asm push si
- X
- X asm mov cx,len
- X
- X asm les si,s
- X
- X asm mov dx,crc32val+2
- X asm mov ax,crc32val
- X
- XcrcNext:
- X asm mov bh,al /* save crc32val[0] */
- X
- X asm mov al,ah /* (crc32 >> 8) & 0x00ffffff */
- X asm mov ah,dl
- X asm mov dl,dh
- X asm xor dh,dh
- X
- X asm mov bl,es:[si]
- X asm inc si
- X
- X asm xor bl,bh /* crcval[0] */
- X
- X asm xor bh,bh
- X asm shl bx,1
- X asm shl bx,1
- X asm xor ax,crc_32_tab[bx]
- X asm xor dx,crc_32_tab[bx+2]
- X
- X asm loop crcNext
- X
- X asm mov crc32val+2,dx
- X asm mov crc32val,ax
- X asm pop si
- X asm pop cx
- X#endif /* TURBOC */
- X}
- SHAR_EOF
- fi
- if test -f 'crc32.h'
- then
- echo shar: "will not over-write existing file 'crc32.h'"
- else
- sed 's/^X//' << \SHAR_EOF > 'crc32.h'
- Xlong crc32val;
- X
- X/* update running CRC calculation with contents of a buffer */
- X
- X#ifndef OLDC
- Xvoid UpdateCRC(unsigned char *s, register int len);
- X#else
- Xvoid UpdateCRC();
- X#endif /* OLDC */
- SHAR_EOF
- fi
- if test -f 'unzip.c'
- then
- echo shar: "will not over-write existing file 'unzip.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'unzip.c'
- X
- X/*
- X * Copyright 1989 Samuel H. Smith; All rights reserved
- X *
- X * Do not distribute modified versions without my permission.
- X * Do not remove or alter this notice or any other copyright notice.
- X * If you use this in your own program you must distribute source code.
- X * Do not use any of this in a commercial product.
- X *
- X */
- X
- X/*
- X * UnZip - A simple zipfile extract utility
- X *
- X * To compile:
- X * tcc -B -O -Z -G -mc unzip.c ;turbo C 2.0, compact model
- X * cl /O /AC /G0 /W3 -c unzip. ;msc 5.1, compact model
- X * cc -O -DOLDC -Dunix {-DHIGH_LOW} {-DSHORTC} -c unzip.c ;unix pcc
- X *
- X * Port to Unix and MSC (i.e. "portable version") by George M. Sipe
- X * (rebel!george).
- X *
- X */
- X
- X#define VERSION \
- X "UnZip: Zipfile Extract v2.0.1 of 09-16-89; (C) 1989 Samuel H. Smith"
- X
- X#ifdef SHORTC
- X#define compressed_size cmpr_sz
- X#define extract_zipfile ext_zip
- X#define filename fn
- X#define follower flwr
- X#define hsize_array_byte hsz_a_byte
- X#define last_mod_file_date mod_fdate
- X#define lit_tree_present lt_present
- X#define maxcodemax mx_cd_mx
- X#define number_disk_with_start_central_directory ndwsc
- X#define process_central_file_header pcfhdr
- X#define process_end_central_dir pecdir
- X#define process_headers proc_hdrs
- X#define total_entries_central_dir tecdir
- X#define version_made_by v_made_by
- X#define LoadTrees LdTrees
- X#endif /* SHORTC */
- X
- Xtypedef unsigned char byte; /* code assumes UNSIGNED bytes */
- Xtypedef long longint; /* sizeof must be 4 bytes */
- Xtypedef unsigned short word; /* sizeof must be 2 bytes */
- Xtypedef char boolean;
- X
- X#define STRSIZ 256
- X
- X#include <stdio.h>
- X /* this is your standard header for all C compiles */
- X
- X#ifndef OLDC
- X#include <stdlib.h>
- X /* this include defines various standard library prototypes */
- X#define VOIDARG void /* function definitions support (void) */
- X#else
- X#include <ctype.h>
- X#define VOIDARG /* function definitions support () only */
- X#endif /* OLDC */
- X
- X
- X/*
- X * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
- X *
- X */
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * Zipfile layout declarations
- X *
- X */
- X
- Xtypedef longint signature_type;
- X
- X
- X#define LOCAL_FILE_HEADER_SIGNATURE 0x04034b50L
- X
- X
- Xtypedef struct local_file_header {
- X word version_needed_to_extract;
- X word general_purpose_bit_flag;
- X word compression_method;
- X word last_mod_file_time;
- X word last_mod_file_date;
- X longint crc32;
- X longint compressed_size;
- X longint uncompressed_size;
- X word filename_length;
- X word extra_field_length;
- X} local_file_header;
- X
- X
- X#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50L
- X
- X
- Xtypedef struct central_directory_file_header {
- X word version_made_by;
- X word version_needed_to_extract;
- X word general_purpose_bit_flag;
- X word compression_method;
- X word last_mod_file_time;
- X word last_mod_file_date;
- X longint crc32;
- X longint compressed_size;
- X longint uncompressed_size;
- X word filename_length;
- X word extra_field_length;
- X word file_comment_length;
- X word disk_number_start;
- X word internal_file_attributes;
- X longint external_file_attributes;
- X longint relative_offset_local_header;
- X} central_directory_file_header;
- X
- X
- X#define END_CENTRAL_DIR_SIGNATURE 0x06054b50L
- X
- X
- Xtypedef struct end_central_dir_record {
- X word number_this_disk;
- X#ifndef TURBOC
- X word num_disk_with_start_cent_dir;
- X word tot_ents_cent_dir_on_this_disk;
- X#else
- X word number_disk_with_start_central_directory;
- X word total_entries_central_dir_on_this_disk;
- X#endif /* TURBOC */
- X word total_entries_central_dir;
- X longint size_central_directory;
- X longint offset_start_central_directory;
- X word zipfile_comment_length;
- X} end_central_dir_record;
- X
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * input file variables
- X *
- X */
- X
- X#define INBUFSIZ 0x2000
- Xbyte *inbuf; /* input file buffer - any size is legal */
- Xbyte *inptr;
- X
- Xint incnt;
- Xunsigned bitbuf;
- Xint bits_left;
- Xboolean zipeof;
- X
- Xint zipfd;
- Xchar zipfn[STRSIZ];
- Xlocal_file_header lrec;
- X
- X#ifdef HIGH_LOW
- Xint w0, w1; /* word translation indices */
- Xint li0, li1, li2, li3; /* long int translation indices */
- X#endif /* HIGH_LOW */
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * output stream variables
- X *
- X */
- X
- X#define OUTBUFSIZ 0x2000 /* must be 0x2000 or larger for unImplode */
- Xbyte *outbuf; /* buffer for rle look-back */
- Xbyte *outptr;
- X
- Xlongint outpos; /* absolute position in outfile */
- Xint outcnt; /* current position in outbuf */
- X
- Xint outfd;
- Xchar filename[STRSIZ];
- Xchar extra[STRSIZ];
- X
- X#define DLE 144
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * shrink/reduce working storage
- X *
- X */
- X
- Xint factor;
- Xbyte followers[256][64];
- Xbyte Slen[256];
- X
- X#define max_bits 13
- X#define init_bits 9
- X#define hsize 8192
- X#define first_ent 257
- X#define clear 256
- X
- Xtypedef int hsize_array_integer[hsize+1];
- Xtypedef byte hsize_array_byte[hsize+1];
- X
- Xhsize_array_integer prefix_of;
- Xhsize_array_byte suffix_of;
- Xhsize_array_byte stack;
- X
- Xint codesize;
- Xint maxcode;
- Xint free_ent;
- Xint maxcodemax;
- Xint offset;
- Xint sizex;
- X
- X
- X
- X/* ============================================================= */
- X/*
- X * Host operating system details
- X *
- X */
- X
- X#include <string.h>
- X /* this include defines strcpy, strcmp, etc. */
- X
- X#ifndef TURBOC
- X#include <sys/types.h>
- X /*
- X * this include file defines
- X * dev_t (* device type *)
- X * as used in the sys/utime.h and sys/stat.h header files below
- X */
- X
- X#ifndef OLDC
- X#include <sys/utime.h>
- X /*
- X * this include file defines
- X * struct utimbuf (* utime buffer structure *)
- X * utime() (* utime function *)
- X * as used in the set_file_time() function defined below
- X */
- X#endif /* !OLDC */
- X#endif /* !TURBOC */
- X
- X#ifndef TURBOC
- X#include <time.h>
- Xstruct ftime {
- X unsigned ft_tsec: 5; /* two seconds */
- X unsigned ft_min: 6; /* minutes */
- X unsigned ft_hour: 5; /* hours */
- X unsigned ft_day: 5; /* days */
- X unsigned ft_month: 4; /* months */
- X unsigned ft_year: 7; /* years - 1980 */
- X};
- X#endif /* TURBOC */
- X#ifndef OLDC
- X#include <io.h>
- X#else
- X#include <sys/file.h>
- X#ifdef L_SET
- X#define SEEK_SET L_SET
- X#else
- X#define SEEK_SET 0
- X#endif /* L_SET */
- X#endif /* OLDC */
- X /*
- X * this include file defines
- X * struct ftime ... (* file time/date stamp info *)
- X * int setftime (int handle, struct ftime *ftimep);
- X * #define SEEK_CUR 1 (* lseek() modes *)
- X * #define SEEK_END 2
- X * #define SEEK_SET 0
- X */
- X
- X#include <fcntl.h>
- X#ifndef O_BINARY
- X#define O_BINARY 0
- X#endif /* O_BINARY */
- X /*
- X * this include file defines
- X * #define O_BINARY 0x8000 (* no cr-lf translation *)
- X * as used in the open() standard function
- X */
- X
- X#include <sys/stat.h>
- X /*
- X * this include file defines
- X * #define S_IREAD 0x0100 (* owner may read *)
- X * #define S_IWRITE 0x0080 (* owner may write *)
- X * as used in the creat() standard function
- X */
- X
- X/* #undef HIGH_LOW - define externally */
- X /*
- X * change 'undef' to 'define' if your machine stores high order bytes in
- X * lower addresses.
- X */
- X
- Xvoid set_file_time(VOIDARG)
- X /*
- X * set the output file date/time stamp according to information from the
- X * zipfile directory record for this file
- X */
- X{
- X union {
- X struct ftime ft; /* system file time record */
- X struct {
- X word ztime; /* date and time words */
- X word zdate; /* .. same format as in .ZIP file */
- X } zt;
- X } td;
- X
- X /*
- X * set output file date and time - this is optional and can be
- X * deleted if your compiler does not easily support setftime()
- X */
- X#ifdef TURBOC
- X td.zt.ztime = lrec.last_mod_file_time;
- X td.zt.zdate = lrec.last_mod_file_date;
- X
- X setftime(outfd, &td.ft);
- X#else
- X
- X#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
- X#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
- X
- X static char month_lengths[] =
- X { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- X int day_of_year, year;
- X#ifndef OLDC
- X struct utimbuf times;
- X#else
- X struct utimbuf {
- X time_t actime; /* file accessed time */
- X time_t modtime; /* file updated time */
- X } times;
- X#endif /* OLDC */
- X
- X /*
- X * this is the standard Unix implementation (also fully
- X * compatible with MSC)
- X */
- X
- X close(outfd);
- X td.zt.ztime = lrec.last_mod_file_time;
- X td.zt.zdate = lrec.last_mod_file_date;
- X year = td.ft.ft_year + 1980;
- X if (td.ft.ft_month < 1 || td.ft.ft_month > 12 || td.ft.ft_day < 1
- X || td.ft.ft_day > month_lengths[td.ft.ft_month-1]
- X && !(td.ft.ft_month == 2 && td.ft.ft_day == 29 && leap (year))
- X || td.ft.ft_hour > 23 || td.ft.ft_min > 59 ||
- X td.ft.ft_tsec*2 > 59)
- X return;
- X day_of_year = td.ft.ft_day - 1;
- X if (td.ft.ft_month > 2 && leap(year)) ++day_of_year;
- X while (--td.ft.ft_month > 0)
- X day_of_year += month_lengths[td.ft.ft_month - 1];
- X times.modtime = (86400 * (long)(day_of_year + 365 * (year - 1970)
- X + nleap (year)) + 3600 * (td.ft.ft_hour-1) + 60 * td.ft.ft_min
- X + td.ft.ft_tsec*2);
- X#ifdef HAVE_TZ
- X tzset();
- X times.modtime += timezone;
- X#endif /* HAVE_TZ */
- X times.actime = times.modtime;
- X utime(filename, ×);
- X#endif /* !TURBOC */
- X}
- X
- X
- Xint create_output_file(VOIDARG)
- X /* return non-0 if creat failed */
- X{
- X /* create the output file with READ and WRITE permissions */
- X outfd = creat(filename, S_IWRITE | S_IREAD | S_IREAD >> 3
- X | S_IREAD >> 6);
- X if (outfd < 1) {
- X printf("Can't create output: %s\n", filename);
- X return 1;
- X }
- X
- X /*
- X * close the newly created file and reopen it in BINARY mode to
- X * disable all CR/LF translations
- X */
- X close(outfd);
- X outfd = open(filename, O_RDWR | O_BINARY);
- X
- X /* write a single byte at EOF to pre-allocate the file */
- X#ifdef tx
- X fsetsize(outfd, lrec.uncompressed_size);
- X#endif /* tx */
- X lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
- X write(outfd, "?", 1);
- X lseek(outfd, 0L, SEEK_SET);
- X return 0;
- X}
- X
- X
- Xint open_input_file(VOIDARG)
- X /* return non-0 if creat failed */
- X{
- X /*
- X * open the zipfile for reading and in BINARY mode to prevent cr/lf
- X * translation, which would corrupt the bitstreams
- X */
- X
- X zipfd = open(zipfn, O_RDONLY | O_BINARY);
- X if (zipfd < 1) {
- X printf("Can't open input file: %s\n", zipfn);
- X return (1);
- X }
- X return 0;
- X}
- X
- X
- X#ifdef HIGH_LOW
- X
- X#ifndef OLDC
- Xvoid swap_bytes(word *wordp)
- X#else
- Xvoid swap_bytes(wordp)
- Xword *wordp;
- X#endif /* OLDC */
- X /* convert intel style 'short int' variable to host format */
- X{
- X char *charp = (char *) wordp;
- X char temp[2];
- X
- X temp[0] = charp[w0];
- X temp[1] = charp[w1];
- X charp[0] = temp[0];
- X charp[1] = temp[1];
- X}
- X
- X#ifndef OLDC
- Xvoid swap_lbytes(longint *longp)
- X#else
- Xvoid swap_lbytes(longp)
- Xlongint *longp;
- X#endif /* OLDC */
- X /* convert intel style 'long' variable to host format */
- X{
- X char *charp = (char *) longp;
- X char temp[4];
- X
- X temp[0] = charp[li0];
- X temp[1] = charp[li1];
- X temp[2] = charp[li2];
- X temp[3] = charp[li3];
- X charp[0] = temp[0];
- X charp[1] = temp[1];
- X charp[2] = temp[2];
- X charp[3] = temp[3];
- X}
- X
- X#endif /* HIGH_LOW */
- X
- X
- X
- X/* ============================================================= */
- X
- Xint FillBuffer(VOIDARG)
- X /* fill input buffer if possible */
- X{
- X int readsize;
- X
- X if (lrec.compressed_size <= 0)
- X return incnt = 0;
- X
- X if (lrec.compressed_size > INBUFSIZ)
- X readsize = INBUFSIZ;
- X else
- X readsize = (int) lrec.compressed_size;
- X incnt = read(zipfd, inbuf, readsize);
- X
- X lrec.compressed_size -= incnt;
- X inptr = inbuf;
- X return incnt--;
- X}
- X
- X#ifndef OLDC
- Xint ReadByte(unsigned *x)
- X#else
- Xint ReadByte(x)
- Xunsigned *x;
- X#endif /* OLDC */
- X /* read a byte; return 8 if byte available, 0 if not */
- X{
- X if (incnt-- == 0)
- X if (FillBuffer() == 0)
- X return 0;
- X
- X *x = *inptr++;
- X return 8;
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- Xstatic unsigned mask_bits[] =
- X {0, 0x0001, 0x0003, 0x0007, 0x000f,
- X 0x001f, 0x003f, 0x007f, 0x00ff,
- X 0x01ff, 0x03ff, 0x07ff, 0x0fff,
- X 0x1fff, 0x3fff, 0x7fff, 0xffff
- X };
- X
- X
- X#ifndef OLDC
- Xint FillBitBuffer(register int bits)
- X#else
- Xint FillBitBuffer(bits)
- Xregister int bits;
- X#endif /* OLDC */
- X /* read a byte; return 8 if byte available, 0 if not */
- X{
- X /* get the bits that are left and read the next word */
- X unsigned temp;
- X register int result = bitbuf;
- X int sbits = bits_left;
- X bits -= bits_left;
- X
- X /* read next word of input */
- X bits_left = ReadByte(&bitbuf);
- X bits_left += ReadByte(&temp);
- X bitbuf |= (temp << 8);
- X if (bits_left == 0)
- X zipeof = 1;
- X
- X /* get the remaining bits */
- X result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
- X bitbuf >>= bits;
- X bits_left -= bits;
- X return result;
- X}
- X
- X#define READBIT(nbits,zdest,ztype) \
- X { if (nbits <= bits_left) \
- X { zdest = ztype(bitbuf & mask_bits[nbits]); \
- X bitbuf >>= nbits; bits_left -= nbits; } \
- X else zdest = ztype(FillBitBuffer(nbits));}
- X
- X/*
- X * macro READBIT(nbits,zdest,ztype)
- X * {
- X * if (nbits <= bits_left) {
- X * zdest = ztype(bitbuf & mask_bits[nbits]);
- X * bitbuf >>= nbits;
- X * bits_left -= nbits;
- X * } else
- X * zdest = ztype(FillBitBuffer(nbits));
- X * }
- X *
- X */
- X
- X
- X/* ------------------------------------------------------------- */
- X
- X#include "crc32.h"
- X
- X
- X/* ------------------------------------------------------------- */
- X
- Xvoid FlushOutput(VOIDARG)
- X /* flush contents of output buffer */
- X{
- X UpdateCRC(outbuf, outcnt);
- X write(outfd, outbuf, outcnt);
- X outpos += outcnt;
- X outcnt = 0;
- X outptr = outbuf;
- X}
- X
- X#define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
- X
- X/*
- X * macro OUTB(intc)
- X * {
- X * *outptr++=intc;
- X * if (++outcnt==OUTBUFSIZ)
- X * FlushOutput();
- X * }
- X *
- X */
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid LoadFollowers(VOIDARG)
- X{
- X register int x;
- X register int i;
- X
- X for (x = 255; x >= 0; x--) {
- X READBIT(6,Slen[x],(byte));
- X for (i = 0; i < Slen[x]; i++) {
- X READBIT(8,followers[x][i],(byte));
- X }
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * The Reducing algorithm is actually a combination of two
- X * distinct algorithms. The first algorithm compresses repeated
- X * byte sequences, and the second algorithm takes the compressed
- X * stream from the first algorithm and applies a probabilistic
- X * compression method.
- X */
- X
- Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
- X
- Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
- Xint D_mask[] = {0, 0x01, 0x03, 0x07, 0x0f};
- X
- Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
- X 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
- X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8};
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid unReduce(VOIDARG)
- X /* expand probablisticly reduced data */
- X{
- X register int lchar;
- X int nchar;
- X int ExState;
- X int V;
- X int Len;
- X
- X factor = lrec.compression_method - 1;
- X ExState = 0;
- X lchar = 0;
- X LoadFollowers();
- X
- X while (((outpos+outcnt) < lrec.uncompressed_size) && (!zipeof)) {
- X if (Slen[lchar] == 0)
- X READBIT(8,nchar,(int)) /* ; */
- X else
- X {
- X READBIT(1,nchar,(int));
- X if (nchar != 0)
- X READBIT(8,nchar,(int)) /* ; */
- X else
- X {
- X int follower;
- X int bitsneeded = B_table[Slen[lchar]];
- X READBIT(bitsneeded,follower,(int));
- X nchar = followers[lchar][follower];
- X }
- X }
- X
- X /* expand the resulting byte */
- X switch (ExState) {
- X
- X case 0:
- X if (nchar != DLE)
- X OUTB((byte) nchar) /*;*/
- X else
- X ExState = 1;
- X break;
- X
- X case 1:
- X if (nchar != 0) {
- X V = nchar;
- X Len = V & L_table[factor];
- X if (Len == L_table[factor])
- X ExState = 2;
- X else
- X ExState = 3;
- X }
- X else {
- X OUTB(DLE);
- X ExState = 0;
- X }
- X break;
- X
- X case 2: {
- X Len += nchar;
- X ExState = 3;
- X }
- X break;
- X
- X case 3: {
- X register int i = Len + 3;
- X int offset = (((V >> D_shift[factor]) &
- X D_mask[factor]) << 8) + nchar + 1;
- X longint op = (outpos+outcnt) - offset;
- X
- X /* special case- before start of file */
- X while ((op < 0L) && (i > 0)) {
- X OUTB(0);
- X op++;
- X i--;
- X }
- X
- X /* normal copy of data from output buffer */
- X {
- X register int ix = (int) (op % OUTBUFSIZ);
- X
- X /* do a block memory copy if possible */
- X if ( ((ix +i) < OUTBUFSIZ) &&
- X ((outcnt+i) < OUTBUFSIZ) ) {
- X memcpy(outptr,&outbuf[ix],i);
- X outptr += i;
- X outcnt += i;
- X }
- X
- X /* otherwise copy byte by byte */
- X else while (i--) {
- X OUTB(outbuf[ix]);
- X if (++ix >= OUTBUFSIZ)
- X ix = 0;
- X }
- X }
- X
- X ExState = 0;
- X }
- X break;
- X }
- X
- X /* store character for next iteration */
- X lchar = nchar;
- X }
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- X/*
- X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
- X * with partial clearing.
- X *
- X */
- X
- Xvoid partial_clear(VOIDARG)
- X{
- X register int pr;
- X register int cd;
- X
- X /* mark all nodes as potentially unused */
- X for (cd = first_ent; cd < free_ent; cd++)
- X prefix_of[cd] |= 0x8000;
- X
- X /* unmark those that are used by other nodes */
- X for (cd = first_ent; cd < free_ent; cd++) {
- X pr = prefix_of[cd] & 0x7fff; /* reference to another node? */
- X if (pr >= first_ent) /* flag node as referenced */
- X prefix_of[pr] &= 0x7fff;
- X }
- X
- X /* clear the ones that are still marked */
- X for (cd = first_ent; cd < free_ent; cd++)
- X if ((prefix_of[cd] & 0x8000) != 0)
- X prefix_of[cd] = -1;
- X
- X /* find first cleared node as next free_ent */
- X cd = first_ent;
- X while ((cd < maxcodemax) && (prefix_of[cd] != -1))
- X cd++;
- X free_ent = cd;
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- X
- Xvoid unShrink(VOIDARG)
- X{
- X#define GetCode(dest) READBIT(codesize,dest,(int))
- X
- X register int code;
- X register int stackp;
- X int finchar;
- X int oldcode;
- X int incode;
- X
- X
- X /* decompress the file */
- X maxcodemax = 1 << max_bits;
- X codesize = init_bits;
- X maxcode = (1 << codesize) - 1;
- X free_ent = first_ent;
- X offset = 0;
- X sizex = 0;
- X
- X for (code = maxcodemax; code > 255; code--)
- X prefix_of[code] = -1;
- X
- X for (code = 255; code >= 0; code--) {
- X prefix_of[code] = 0;
- X suffix_of[code] = (byte) code;
- X }
- X
- X GetCode(oldcode);
- X if (zipeof)
- X return;
- X finchar = oldcode;
- X
- X OUTB((byte) finchar);
- X
- X stackp = hsize;
- X
- X while (!zipeof) {
- X GetCode(code);
- X if (zipeof)
- X return;
- X
- X while (code == clear) {
- X GetCode(code);
- X switch (code) {
- X
- X case 1:{
- X codesize++;
- X if (codesize == max_bits)
- X maxcode = maxcodemax;
- X else
- X maxcode = (1 << codesize) - 1;
- X }
- X break;
- X
- X case 2:
- X partial_clear();
- X break;
- X }
- X
- X GetCode(code);
- X if (zipeof)
- X return;
- X }
- X
- X
- X /* special case for KwKwK string */
- X incode = code;
- X if (prefix_of[code] == -1) {
- X stack[--stackp] = (byte) finchar;
- X code = oldcode;
- X }
- X
- X
- X /* generate output characters in reverse order */
- X while (code >= first_ent) {
- X stack[--stackp] = suffix_of[code];
- X code = prefix_of[code];
- X }
- X
- X finchar = suffix_of[code];
- X stack[--stackp] = (byte) finchar;
- X
- X
- X /* and put them out in forward order, block copy */
- X if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
- X memcpy(outptr,&stack[stackp],hsize-stackp);
- X outptr += hsize-stackp;
- X outcnt += hsize-stackp;
- X stackp = hsize;
- X }
- X
- X /* output byte by byte if we can't go by blocks */
- X else while (stackp < hsize)
- X OUTB(stack[stackp++]);
- X
- X
- X /* generate new entry */
- X code = free_ent;
- X if (code < maxcodemax) {
- X prefix_of[code] = oldcode;
- X suffix_of[code] = (byte) finchar;
- X
- X do
- X code++;
- X while ((code < maxcodemax) && (prefix_of[code] != -1));
- X
- X free_ent = code;
- X }
- X
- X /* remember previous code */
- X oldcode = incode;
- X }
- X
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- X/*
- X * Imploding
- X * ---------
- X *
- X * The Imploding algorithm is actually a combination of two distinct
- X * algorithms. The first algorithm compresses repeated byte sequences
- X * using a sliding dictionary. The second algorithm is used to compress
- X * the encoding of the sliding dictionary ouput, using multiple
- X * Shannon-Fano trees.
- X *
- X */
- X
- X#define maxSF 256
- X
- X typedef struct sf_entry {
- X word Code;
- X byte Value;
- X byte BitLength;
- X } sf_entry;
- X
- X typedef struct sf_tree { /* a shannon-fano tree */
- X sf_entry entry[maxSF];
- X int entries;
- X int MaxLength;
- X } sf_tree;
- X
- X typedef sf_tree *sf_treep;
- X
- X sf_tree lit_tree;
- X sf_tree length_tree;
- X sf_tree distance_tree;
- X boolean lit_tree_present;
- X boolean eightK_dictionary;
- X int minimum_match_length;
- X int dict_bits;
- X
- X
- X#ifndef OLDC
- Xvoid SortLengths(sf_tree *tree)
- X#else
- Xvoid SortLengths(tree)
- Xsf_tree *tree;
- X#endif /* OLDC */
- X /* Sort the Bit Lengths in ascending order, while retaining the order
- X of the original lengths stored in the file */
- X{
- X int x;
- X int gap;
- X sf_entry t;
- X boolean noswaps;
- X int a, b;
- X
- X gap = tree->entries / 2;
- X
- X do {
- X do {
- X noswaps = 1;
- X for (x = 0; x <= (tree->entries - 1) - gap; x++)
- X {
- X a = tree->entry[x].BitLength;
- X b = tree->entry[x + gap].BitLength;
- X if ((a > b) || ((a == b) && (tree->entry[x].Value > tree->entry[x + gap].Value)))
- X {
- X t = tree->entry[x];
- X tree->entry[x] = tree->entry[x + gap];
- X tree->entry[x + gap] = t;
- X noswaps = 0;
- X }
- X }
- X } while (!noswaps);
- X
- X gap = gap / 2;
- X } while (gap > 0);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid ReadLengths(sf_tree *tree)
- X#else
- Xvoid ReadLengths(tree)
- Xsf_tree *tree;
- X#endif /* OLDC */
- X{
- X int treeBytes;
- X int i;
- X int num, len;
- X
- X /* get number of bytes in compressed tree */
- X READBIT(8,treeBytes,(int));
- X treeBytes++;
- X i = 0;
- X
- X tree->MaxLength = 0;
- X
- X /* High 4 bits: Number of values at this bit length + 1. (1 - 16)
- X Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) */
- X while (treeBytes > 0)
- X {
- X READBIT(4,len,(int)); len++;
- X READBIT(4,num,(int)); num++;
- X
- X while (num > 0)
- X {
- X if (len > tree->MaxLength)
- X tree->MaxLength = len;
- X tree->entry[i].BitLength = (byte) len;
- X tree->entry[i].Value = (byte) i;
- X i++;
- X num--;
- X }
- X
- X treeBytes--;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid GenerateTrees(sf_tree *tree)
- X#else
- Xvoid GenerateTrees(tree)
- Xsf_tree *tree;
- X#endif /* OLDC */
- X /* Generate the Shannon-Fano trees */
- X{
- X word Code;
- X int CodeIncrement;
- X int LastBitLength;
- X int i;
- X
- X
- X Code = 0;
- X CodeIncrement = 0;
- X LastBitLength = 0;
- X
- X i = tree->entries - 1; /* either 255 or 63 */
- X while (i >= 0)
- X {
- X Code += CodeIncrement;
- X if (tree->entry[i].BitLength != (byte) LastBitLength)
- X {
- X LastBitLength = tree->entry[i].BitLength;
- X CodeIncrement = 1 << (16 - LastBitLength);
- X }
- X
- X tree->entry[i].Code = Code;
- X i--;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid ReverseBits(sf_tree *tree)
- X#else
- Xvoid ReverseBits(tree)
- Xsf_tree *tree;
- X#endif /* OLDC */
- X /* Reverse the order of all the bits in the above ShannonCode[]
- X vector, so that the most significant bit becomes the least
- X significant bit. For example, the value 0x1234 (hex) would become
- X 0x2C48 (hex). */
- X{
- X int i;
- X word mask;
- X word revb;
- X word v;
- X word o;
- X int b;
- X
- X
- X for (i = 0; i <= tree->entries - 1; i++)
- X {
- X /* get original code */
- X o = tree->entry[i].Code;
- X
- X /* reverse each bit */
- X mask = 0x0001;
- X revb = 0x8000;
- X v = 0;
- X for (b = 0; b <= 15; b++)
- X {
- X /* if bit set in mask, then substitute reversed bit */
- X if ((o & mask) != 0)
- X v = v | revb;
- X
- X /* advance to next bit */
- X revb = (revb >> 1);
- X mask = (mask << 1);
- X }
- X
- X /* store reversed bits */
- X tree->entry[i].Code = v;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid LoadTree(sf_tree *tree, int treesize)
- X#else
- Xvoid LoadTree(tree, treesize)
- Xsf_tree *tree;
- Xint treesize;
- X#endif /* OLDC */
- X /* allocate and load a shannon-fano tree from the compressed file */
- X{
- X tree->entries = treesize;
- X ReadLengths(tree);
- X SortLengths(tree);
- X GenerateTrees(tree);
- X ReverseBits(tree);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid LoadTrees(void)
- X#else
- Xvoid LoadTrees()
- X#endif /* OLDC */
- X{
- X /* bit 1... */
- X eightK_dictionary = (boolean) ((lrec.general_purpose_bit_flag & 0x02) != 0);
- X /* bit 2... */
- X lit_tree_present = (boolean) ((lrec.general_purpose_bit_flag & 0x04) != 0);
- X
- X if (eightK_dictionary)
- X dict_bits = 7;
- X else
- X dict_bits = 6;
- X
- X if (lit_tree_present)
- X {
- X minimum_match_length = 3;
- X LoadTree(&lit_tree,256);
- X }
- X else
- X minimum_match_length = 2;
- X
- X LoadTree(&length_tree,64);
- X LoadTree(&distance_tree,64);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid ReadTree(sf_tree *tree, int *dest)
- X#else
- Xvoid ReadTree(tree, dest)
- Xsf_tree *tree;
- Xint *dest;
- X#endif /* OLDC */
- X /* read next byte using a shannon-fano tree */
- X{
- X int bits = 0;
- X word cv = 0;
- X int cur = 0;
- X int b;
- X
- X *dest = -1; /* in case of error */
- X
- X for (;;)
- X {
- X READBIT(1,b,(int));
- X cv = cv | (b << bits);
- X bits++;
- X
- X /* this is a very poor way of decoding shannon-fano. two quicker
- X methods come to mind:
- X a) arrange the tree as a huffman-style binary tree with
- X a "leaf" indicator at each node,
- X and
- X b) take advantage of the fact that s-f codes are at most 8
- X bits long and alias unused codes for all bits following
- X the "leaf" bit.
- X */
- X
- X while (tree->entry[cur].BitLength < (byte) bits)
- X {
- X cur++;
- X if (cur >= tree->entries)
- X return; /* data error */
- X }
- X
- X while (tree->entry[cur].BitLength == (byte) bits)
- X {
- X if (tree->entry[cur].Code == cv)
- X {
- X *dest = tree->entry[cur].Value;
- X return;
- X }
- X
- X cur++;
- X if (cur >= tree->entries)
- X return; /* data error */
- X }
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid unImplode(void)
- X#else
- Xvoid unImplode()
- X#endif /* OLDC */
- X /* expand imploded data */
- X
- X{
- X int lout;
- X longint op;
- X int Length;
- X int Distance;
- X
- X LoadTrees();
- X
- X while ((!zipeof) && ((outpos+outcnt) < lrec.uncompressed_size))
- X {
- X READBIT(1,lout,(int));
- X
- X if (lout != 0) /* encoded data is literal data */
- X {
- X if (lit_tree_present) /* use Literal Shannon-Fano tree */
- X ReadTree(&lit_tree,&lout);
- X else
- X READBIT(8,lout,(int));
- X
- X OUTB((byte) lout);
- X }
- X else /* encoded data is sliding dictionary match */
- X {
- X READBIT(dict_bits,lout,(int));
- X Distance = lout;
- X
- X ReadTree(&distance_tree,&lout);
- X Distance |= (lout << dict_bits);
- X /* using the Distance Shannon-Fano tree, read and decode the
- X upper 6 bits of the Distance value */
- X
- X ReadTree(&length_tree,&Length);
- X /* using the Length Shannon-Fano tree, read and decode the
- X Length value */
- X
- X Length += minimum_match_length;
- X if (Length == (63 + minimum_match_length))
- X {
- X READBIT(8,lout,(int));
- X Length += lout;
- X }
- X
- X /* move backwards Distance+1 bytes in the output stream, and copy
- X Length characters from this position to the output stream.
- X (if this position is before the start of the output stream,
- X then assume that all the data before the start of the output
- X stream is filled with zeros) */
- X
- X op = (outpos+outcnt) - Distance - 1L;
- X
- X /* special case- before start of file */
- X while ((op < 0L) && (Length > 0)) {
- X OUTB(0);
- X op++;
- X Length--;
- X }
- X
- X /* normal copy of data from output buffer */
- X {
- X register int ix = (int) (op % OUTBUFSIZ);
- X
- X /* do a block memory copy if possible */
- X if ( ((ix +Length) < OUTBUFSIZ) &&
- X ((outcnt+Length) < OUTBUFSIZ) ) {
- X memcpy(outptr,&outbuf[ix],Length);
- X outptr += Length;
- X outcnt += Length;
- X }
- X
- X /* otherwise copy byte by byte */
- X else while (Length--) {
- X OUTB(outbuf[ix]);
- X if (++ix >= OUTBUFSIZ)
- X ix = 0;
- X }
- X }
- X }
- X }
- X}
- X
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid extract_member(VOIDARG)
- X{
- X unsigned b;
- X
- X bits_left = 0;
- X bitbuf = 0;
- X incnt = 0;
- X outpos = 0L;
- X outcnt = 0;
- X outptr = outbuf;
- X zipeof = 0;
- X crc32val = 0xFFFFFFFFL;
- X
- X
- X /* create the output file with READ and WRITE permissions */
- X if (create_output_file())
- X exit(1);
- X
- X switch (lrec.compression_method) {
- X
- X case 0: /* stored */
- X {
- X printf(" Extracting: %-12s ", filename);
- X while (ReadByte(&b))
- X OUTB((byte) b);
- X }
- X break;
- X
- X case 1: {
- X printf("UnShrinking: %-12s ", filename);
- X unShrink();
- X }
- X break;
- X
- X case 2:
- X case 3:
- X case 4:
- X case 5: {
- X printf(" Expanding: %-12s ", filename);
- X unReduce();
- X }
- X break;
- X
- X case 6: {
- X printf(" Exploding: %-12s ", filename);
- X unImplode();
- X }
- X break;
- X
- X default:
- X printf("Unknown compression method.");
- X }
- X
- X
- X /* write the last partial buffer, if any */
- X if (outcnt > 0) {
- X UpdateCRC(outbuf, outcnt);
- X write(outfd, outbuf, outcnt);
- X }
- X
- X /* set output file date and time */
- X set_file_time();
- X
- X close(outfd);
- X
- X crc32val = -1 - crc32val;
- X if (crc32val != lrec.crc32)
- X printf(" Bad CRC %08lx (should be %08lx)", lrec.crc32, crc32val);
- X
- X printf("\n");
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- X#ifndef OLDC
- Xvoid get_string(int len, char *s)
- X#else
- Xvoid get_string(len, s)
- Xint len;
- Xchar *s;
- X#endif /* OLDC */
- X /* read a byte; return 8 if byte available, 0 if not */
- X{
- X read(zipfd, s, len);
- X s[len] = 0;
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_local_file_header(VOIDARG)
- X{
- X if ((long) &lrec.crc32 ==
- X (long) &lrec.last_mod_file_date
- X + sizeof(lrec.last_mod_file_date))
- X read(zipfd, (char *) &lrec, sizeof(lrec));
- X else {
- X read(zipfd, (char *) &lrec, (unsigned)
- X ((long) &lrec.last_mod_file_date
- X + sizeof(lrec.last_mod_file_date)
- X - (long) &lrec));
- X read(zipfd, (char *) &lrec.crc32, (unsigned)
- X ((long) &lrec.extra_field_length
- X + sizeof(lrec.extra_field_length)
- X - (long) &lrec.crc32));
- X }
- X
- X#ifdef HIGH_LOW
- X swap_bytes(&lrec.version_needed_to_extract);
- X swap_bytes(&lrec.general_purpose_bit_flag);
- X swap_bytes(&lrec.compression_method);
- X swap_bytes(&lrec.last_mod_file_time);
- X swap_bytes(&lrec.last_mod_file_date);
- X swap_lbytes(&lrec.crc32);
- X swap_lbytes(&lrec.compressed_size);
- X swap_lbytes(&lrec.uncompressed_size);
- X swap_bytes(&lrec.filename_length);
- X swap_bytes(&lrec.extra_field_length);
- X#endif /* HIGH_LOW */
- X
- X get_string(lrec.filename_length, filename);
- X get_string(lrec.extra_field_length, extra);
- X#ifdef unix
- X {
- X char *cp;
- X for (cp = filename; *cp; ++cp)
- X if (isupper(*cp)) *cp = tolower(*cp);
- X }
- X#endif /* unix */
- X extract_member();
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_central_file_header(VOIDARG)
- X{
- X central_directory_file_header rec;
- X char filename[STRSIZ];
- X char extra[STRSIZ];
- X char comment[STRSIZ];
- X
- X if ((long) &rec.external_file_attributes ==
- X (long) &rec.internal_file_attributes
- X + sizeof(rec.internal_file_attributes))
- X read(zipfd, (char *) &rec, sizeof(rec));
- X else {
- X read(zipfd, (char *) &rec, (unsigned)
- X ((long) &rec.internal_file_attributes
- X + sizeof(rec.internal_file_attributes)
- X - (long) &rec));
- X read(zipfd, (char *) &rec.external_file_attributes, (unsigned)
- X ((long) &rec.relative_offset_local_header
- X + sizeof(rec.relative_offset_local_header)
- X - (long) &rec.external_file_attributes));
- X }
- X
- X#ifdef HIGH_LOW
- X swap_bytes(&rec.version_made_by);
- X swap_bytes(&rec.version_needed_to_extract);
- X swap_bytes(&rec.general_purpose_bit_flag);
- X swap_bytes(&rec.compression_method);
- X swap_bytes(&rec.last_mod_file_time);
- X swap_bytes(&rec.last_mod_file_date);
- X swap_lbytes(&rec.crc32);
- X swap_lbytes(&rec.compressed_size);
- X swap_lbytes(&rec.uncompressed_size);
- X swap_bytes(&rec.filename_length);
- X swap_bytes(&rec.extra_field_length);
- X swap_bytes(&rec.file_comment_length);
- X swap_bytes(&rec.disk_number_start);
- X swap_bytes(&rec.internal_file_attributes);
- X swap_lbytes(&rec.external_file_attributes);
- X swap_lbytes(&rec.relative_offset_local_header);
- X#endif /* HIGH_LOW */
- X
- X get_string(rec.filename_length, filename);
- X get_string(rec.extra_field_length, extra);
- X get_string(rec.file_comment_length, comment);
- X#ifdef unix
- X {
- X char *cp;
- X for (cp = filename; *cp; ++cp)
- X if (isupper(*cp)) *cp = tolower(*cp);
- X }
- X#endif /* unix */
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_end_central_dir(VOIDARG)
- X{
- X end_central_dir_record rec;
- X char comment[STRSIZ];
- X
- X read(zipfd, (char *) &rec, sizeof(rec));
- X
- X#ifdef HIGH_LOW
- X swap_bytes(&rec.number_this_disk);
- X#ifndef TURBOC
- X swap_bytes(&rec.num_disk_with_start_cent_dir);
- X swap_bytes(&rec.tot_ents_cent_dir_on_this_disk);
- X#else
- X swap_bytes(&rec.number_disk_with_start_central_directory);
- X swap_bytes(&rec.total_entries_central_dir_on_this_disk);
- X#endif /* TURBOC */
- X swap_bytes(&rec.total_entries_central_dir);
- X swap_lbytes(&rec.size_central_directory);
- X swap_lbytes(&rec.offset_start_central_directory);
- X swap_bytes(&rec.zipfile_comment_length);
- X#endif /* HIGH_LOW */
- X
- X get_string(rec.zipfile_comment_length, comment);
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_headers(VOIDARG)
- X{
- X longint sig;
- X
- X while (1) {
- X if (read(zipfd, (char *) &sig, sizeof(sig)) != sizeof(sig))
- X return;
- X
- X#ifdef HIGH_LOW
- X swap_lbytes(&sig);
- X#endif /* HIGH_LOW */
- X
- X if (sig == LOCAL_FILE_HEADER_SIGNATURE)
- X process_local_file_header();
- X else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
- X process_central_file_header();
- X else if (sig == END_CENTRAL_DIR_SIGNATURE) {
- X process_end_central_dir();
- X return;
- X }
- X else {
- X printf("Invalid Zipfile Header (0x%.8lx)\n", sig);
- X return;
- X }
- X }
- X
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid extract_zipfile(VOIDARG)
- X{
- X /*
- X * open the zipfile for reading and in BINARY mode to prevent cr/lf
- X * translation, which would corrupt the bitstreams
- X */
- X
- X if (open_input_file())
- X exit(1);
- X
- X#ifdef HIGH_LOW
- X {
- X word w_sig;
- X longint li_sig;
- X char *bp, *bp0 = (char *)&li_sig, *bp3 = ((char *)&li_sig)+3;
- X
- X if (read(zipfd, (char *) &w_sig, 2) == 2)
- X if (w_sig == (LOCAL_FILE_HEADER_SIGNATURE & 0xffff)) {
- X w0 = 0;
- X w1 = 1;
- X } else {
- X w0 = 1;
- X w1 = 0;
- X }
- X lseek(zipfd, 0L, SEEK_SET);
- X if (read(zipfd, (char *) &li_sig, 4) == 4)
- X if (li_sig == LOCAL_FILE_HEADER_SIGNATURE) {
- X li0 = 0;
- X li1 = 1;
- X li2 = 2;
- X li3 = 3;
- X } else {
- X li0 = li1 = li2 = li3 = 0;
- X for (bp = bp0; bp < bp3; ++bp, ++li0)
- X if (*bp < 0x4b && !(*bp & 0x01))
- X break;
- X for (bp = bp0; bp < bp3; ++bp, ++li1)
- X if (*bp < 0x4b && (*bp & 0x01))
- X break;
- X for (bp = bp0; bp < bp3; ++bp, ++li2)
- X if (*bp == ((LOCAL_FILE_HEADER_SIGNATURE
- X >> 8) & 0xffL))
- X break;
- X for (bp = bp0; bp < bp3; ++bp, ++li3)
- X if (*bp == (LOCAL_FILE_HEADER_SIGNATURE
- X & 0xffL))
- X break;
- X }
- X lseek(zipfd, 0L, SEEK_SET);
- X }
- X#endif /* HIGH_LOW */
- X
- X process_headers();
- X
- X close(zipfd);
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X/*
- X * main program
- X *
- X */
- X
- X#ifndef OLDC
- Xvoid main(int argc, char **argv)
- X#else
- Xvoid main(argc, argv)
- Xint argc;
- Xchar **argv;
- X#endif /* OLDC */
- X /* read a byte; return 8 if byte available, 0 if not */
- X{
- X if (argc != 2) {
- X printf("\n%s\nCourtesy of: S.H.Smith and The Tool Shop BBS, (602) 279-2673.\n\n",VERSION);
- X printf("You may copy and distribute this program freely, provided that:\n");
- X printf(" 1) No fee is charged for such copying and distribution, and\n");
- X printf(" 2) It is distributed ONLY in its original, unmodified state.\n\n");
- X printf("If you wish to distribute a modified version of this program, you MUST\n");
- X printf("include the source code.\n\n");
- X printf("If you modify this program, I would appreciate a copy of the new source\n");
- X printf("code. I am holding the copyright on the source code, so please don't\n");
- X printf("delete my name from the program files or from the documentation.\n\n");
- X printf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
- X printf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
- X printf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
- X printf("CLAIM BY ANY OTHER PARTY.\n\n");
- X printf("Usage: UnZip FILE[.zip]\n");
- X exit(1);
- X }
- X
- X /* .ZIP default if none provided by user */
- X strcpy(zipfn, argv[1]);
- X if (strchr(zipfn, '.') == NULL)
- X strcat(zipfn, ".zip");
- X
- X /* allocate i/o buffers */
- X inbuf = (byte *) (malloc(INBUFSIZ));
- X outbuf = (byte *) (malloc(OUTBUFSIZ));
- X if ((inbuf == NULL) || (outbuf == NULL)) {
- X printf("Can't allocate buffers!\n");
- X exit(1);
- X }
- X
- X /* do the job... */
- X extract_zipfile();
- X exit(0);
- X}
- X
- SHAR_EOF
- fi
- if test -f 'unzip.doc'
- then
- echo shar: "will not over-write existing file 'unzip.doc'"
- else
- sed 's/^X//' << \SHAR_EOF > 'unzip.doc'
- X
- X UnZip
- X
- X Version 2.0.1, 09-16-89
- X
- X Zipfile Extract Utility
- X
- X Copyright (C) 1989 Samuel H. Smith; ALL RIGHTS RESERVED
- X
- X
- X'UnZip' is a small Zipfile extract utility. It is written to be as
- Xsmall and portable as possible -- ideal as a starting point for handling
- X.ZIP files in non-IBM environments.
- X
- XSource code is provided in C and Turbo Pascal. If you port this program
- Xto a non-IBM system, I would appreciate a copy of the ported source and
- Xexec files.
- X
- X
- XUsage
- X-----
- X unz filename[.zip] ;pascal language version
- X unzip filename[.zip] ;C language version
- X
- X
- XRevision history
- X----------------
- X
- X3-3-89
- X Initial alpha test release.
- X
- X3-5-89
- X First fully operational release. Does not implement CRC verification,
- X but should correctly unzip all compression methods.
- X
- X3-6-89
- X Corrected end-of-file detection in both shrink and reduce expanders.
- X Resulting files should now always have the correct size. Added ".ZIP"
- X default to unzip.c to match calling conventions of unz.pas.
- X
- X3-8-89
- X Moved machine and operating-system specific code to a block starting
- X around line 180. Added code to swap bytes on host machines that
- X store the high order bytes in lower address locations than the low
- X order bytes.
- X
- X3-15-89
- X Added CRC checking in UNZIP.C. Speeded operation by about 150%.
- X
- X I'm spending my time on the C version now and don't plan to do any
- X further work on the pascal. If you're using the pascal version
- X please contact me.
- X
- X9-9-89
- X Addition of new "un-implode" logic to handle new compression format
- X included with PKZ101.
- X
- X9-16-89
- X Portable version created by George M. Sipe (rebel!george). Should
- X now more easily be ported to other systems and compilers.
- X
- X
- X
- XLICENSE
- X=======
- X
- XYou may copy and distribute this program freely, provided that:
- X 1) No fee is charged for such copying and distribution, and
- X 2) It is distributed ONLY in its original, unmodified state.
- X
- XIf you wish to distribute a modified version of this program, you MUST
- Xinclude the source code.
- X
- XIf you modify this program, I would appreciate a copy of the new source
- Xcode. I am holding the copyright on the source code, so please don't
- Xdelete my name from the program files or from the documentation.
- X
- X
- XSUPPORT
- X=======
- X
- XI work very hard to produce a software package of the highest quality
- Xand functionality. I try to look into all reported bugs, and will
- Xgenerally fix reported problems within a few days.
- X
- XIN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST
- XPROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES
- XARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY
- XCLAIM BY ANY OTHER PARTY.
- X
- XIf you have any questions, bugs, or suggestions, please contact me at:
- X
- X The Tool Shop BBS
- X (602) 279-2673 (FREE LINE, USR 2400)
- X (602) 264-3969 (HST 9600)
- X (602) 270-0239 (HAYES 9600)
- X
- XThe latest version is always available for downloading. (Except
- Xpossibly this portable version.)
- X
- XEnjoy! Samuel H. Smith
- X Author and Sysop of The Tool Shop.
- X
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-
- --
- George M. Sipe, Phone: (404) 447-4731
- 537 Lakeshore Drive, Berkeley Lake, GA 30136-3035
- UUCP: ...!{decvax,linus,rutgers}!gatech!rebel!george
-
-
-